//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.ManagementStudioModels
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using SR = Microsoft.Research.DataLayer;
    using System.ComponentModel;
    using System.Windows;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities;
    using System.Globalization;

    public class NodeViewModel : BaseRegMgrModel
    {
        #region Private fields

        /// <summary>
        /// Executer availability.
        /// </summary>
        private SR.ExecutorAvailabiltiy executorAvailability;

        /// <summary>
        /// Executer status.
        /// </summary>
        private SR.MachineStatus machineStatus;

        /// <summary>
        /// Scheduler status.
        /// </summary>
        private SR.SchedulerStatus schedulerStatus;

        /// <summary>
        /// Machine error message.
        /// </summary>
        private string machineErrorMessage;

        /// <summary>
        /// Scheduler error message.
        /// </summary>
        private string schedulerErrorMessage;

        /// <summary>
        /// A guid.
        /// </summary>
        private static Guid parentGuid = Guid.NewGuid();

        /// <summary>
        /// Flag indicating if the model is a complete node view model or just the root.
        /// </summary>
        private bool completeNodeViewModel;

        /// <summary>
        /// Integer number of concurrent jobs in a node
        /// </summary>
        private int maxConcurrentJobs = 1;

        /// <summary>
        /// Type of this machine.
        /// </summary>
        private SR.MachineType machineType;

        /// <summary>
        /// Trident installed directory on this executor
        /// </summary>        
        private string installedDir = string.Empty;

        /// <summary>
        /// Cluster passoword property for HPC HeadNode
        /// </summary>
        private string clusterPassword;

        /// <summary>
        /// Cluster username property for HPC HeadNode
        /// </summary>
        private string clusterUser;

        /// <summary>
        /// 
        /// </summary>
        private bool isInteractive;

        /// <summary>
        /// True if this node is deleted, False otherwise.
        /// </summary>
        private bool isDeleted;

        #endregion

        #region Public properties

        /// <summary>
        ///  A flag indication if the node is deleted.
        /// </summary>
        public bool IsDeleted
        {
            get
            {
                return isDeleted;
            }
            set
            {
                isDeleted = value;
            }
        }

        #endregion

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="node">The registry object.</param>
        public NodeViewModel(SR.Machine node)
        {
            this.Name = node.Name;
            this.Label = this.Name;
            if (node.IsInteractiveExecution)
            {
                this.Label += ManagementStudioResourceManager.GetString("InteractiveNode");
            }

            if (node.Type == SR.MachineType.Virtual)
            {
                this.Label += ManagementStudioResourceManager.GetString("VirtualNode");
            }

            this.Description = node.Description;
            this.Id = ((SR.IObject)node).ID;
            this.machineStatus = node.Status;
            this.schedulerStatus = node.SchedulerStatus;
            this.executorAvailability = node.Availability;
            this.machineErrorMessage = node.ExecutorStatusMessage;
            this.schedulerErrorMessage = node.SchedulerStatusMessage;
            this.LastModifiedBy = node.Updated.User;
            this.LastModifiedTime = node.Updated.When;
            this.CompleteNodeViewModel = true;
            this.maxConcurrentJobs = node.MaxConcurrentJobs;
            this.machineType = node.Type;
            this.clusterPassword = node.ClusterPassword;
            this.clusterUser = node.ClusterUser;
            this.InstalledDir = node.ComputeInstalledDirectory;
            this.isInteractive = node.IsInteractiveExecution;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NodeViewModel"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="label">The label.</param>
        public NodeViewModel(string name, string label)
        {
            if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(name.Trim()))
            {
                throw new ArgumentNullException("name");
            }

            this.Name = name.Trim();
            this.Label = (string.IsNullOrEmpty(label) || string.IsNullOrEmpty(label.Trim())) ? this.Name : label.Trim();
            this.Id = NodeViewModel.parentGuid;
            this.CompleteNodeViewModel = false;
        }

        /// <summary>
        /// Update the model with the new copy of the node.
        /// </summary>
        /// <param name="node">The registry object.</param>
        public void UpdateModel(SR.Machine node)
        {
            this.Name = node.Name;
            this.Label = this.Name;
            if (node.IsInteractiveExecution)
            {
                this.Label += ManagementStudioResourceManager.GetString("InteractiveNode");
            }

            if (node.Type == SR.MachineType.Virtual)
            {
                this.Label += ManagementStudioResourceManager.GetString("VirtualNode");
            }

            this.Description = node.Description;
            this.Id = ((SR.IObject)node).ID;
            this.MachineStatus = node.Status;
            this.SchedulerStatus = node.SchedulerStatus;
            this.ExecutorAvailability = node.Availability;
            this.MachineErrorMessage = node.ExecutorStatusMessage;
            this.SchedulerErrorMessage = node.SchedulerStatusMessage;
            this.LastModifiedBy = node.Updated.User;
            this.LastModifiedTime = node.Updated.When;
            this.maxConcurrentJobs = node.MaxConcurrentJobs;
            this.clusterPassword = node.ClusterPassword;
            this.clusterUser = node.ClusterUser;
            this.installedDir = node.ComputeInstalledDirectory;
        }

        #region Public properties

        /// <summary>
        /// Gets or sets the availability of the machine.
        /// </summary>
        public SR.ExecutorAvailabiltiy ExecutorAvailability
        {
            get
            {
                return this.executorAvailability;
            }
            set
            {
                this.executorAvailability = value;
                this.RaisePropertyChanged("ExecutorAvailability");
            }
        }

        /// <summary>
        /// Gets or sets the current status of the machine.
        /// </summary>
        public SR.MachineStatus MachineStatus
        {
            get
            {
                return this.machineStatus;
            }
            set
            {
                this.machineStatus = value;
                this.RaisePropertyChanged("MachineStatus");
            }
        }

        /// <summary>
        /// Gets or sets the current status of the scheduler.
        /// </summary>
        public SR.SchedulerStatus SchedulerStatus
        {
            get
            {
                return this.schedulerStatus;
            }
            set
            {
                this.schedulerStatus = value;
                this.RaisePropertyChanged("SchedulerStatus");
            }
        }

        /// <summary>
        /// Gets or sets the error message shown when an the executer is down.
        /// </summary>
        public string MachineErrorMessage
        {
            get
            {
                return this.machineErrorMessage;
            }
            set
            {
                this.machineErrorMessage = value;
                this.RaisePropertyChanged("MachineErrorMessage");
            }
        }

        /// <summary>
        /// Gets/sets the max concurrent jobs on a node
        /// </summary>
        public int MaxConcurrentJobs
        {
            get
            {
                return this.maxConcurrentJobs;
            }
            set
            {
                maxConcurrentJobs = value;
                this.RaisePropertyChanged("MaxConcurrentJobs");
            }
        }

        /// <summary>
        /// Gets or sets the error message shown when an the scheduler is down.
        /// </summary>
        public string SchedulerErrorMessage
        {
            get
            {
                return this.schedulerErrorMessage;
            }
            set
            {
                this.schedulerErrorMessage = value;
                this.RaisePropertyChanged("SchedulerErrorMessage");
            }
        }


        /// <summary>
        /// Gets or sets a value indicating whether complete node view model.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if complete node view model; otherwise, <c>false</c>.
        /// </value>
        public bool CompleteNodeViewModel
        {
            get
            {
                return this.completeNodeViewModel;
            }
            set
            {
                this.completeNodeViewModel = value;
                this.RaisePropertyChanged("CompleteNodeViewModel");
            }
        }

        /// <summary>
        /// Updates the installed directory property
        /// </summary>
        public string InstalledDir
        {
            get
            {
                return this.installedDir;
            }
            set
            {
                this.installedDir = value;
            }
        }

        /// <summary>
        /// Updates the cluster username property
        /// </summary>
        public string ClusterUser
        {
            get
            {
                return this.clusterUser;
            }
            set
            {
                this.clusterUser = value;
            }
        }

        /// <summary>
        /// Updates the cluster passoword property
        /// </summary>
        public string ClusterPassword
        {
            get
            {
                return this.clusterPassword;
            }
            set
            {
                this.clusterPassword = value;
            }
        }


        /// <summary>
        /// Gets or sets the machine type.
        /// </summary>
        public SR.MachineType MachineType
        {
            get
            {
                return this.machineType;
            }

            set
            {
                this.machineType = value;
            }
        }

        /// <summary>
        /// Gets a value that specifies if the executor is visible or not.
        /// </summary>
        public Visibility ExecutorVisibility
        {
            get
            {
                Visibility visibility = Visibility.Visible;
                if (this.machineType == SR.MachineType.HPCComputeNode)
                {
                    visibility = Visibility.Collapsed;
                }

                return visibility;
            }
        }

        /// <summary>
        /// Gets a value that specifies if the executor is visible or not.
        /// </summary>
        public Visibility HpcCluster
        {
            get
            {
                Visibility visibility = Visibility.Collapsed;
                if (this.MachineType == SR.MachineType.HPCCluster)
                {
                    visibility = Visibility.Visible;
                }

                return visibility;
            }
        }

        #endregion

        /// <summary>
        /// Override for the tostring base method. Used predominantly as automation ids for databound controls.
        /// </summary>
        /// <returns>The string representation of the object.</returns>
        public override string ToString()
        {
            if (!string.IsNullOrEmpty(this.Name))
            {
                return string.Format(CultureInfo.CurrentCulture, "{0}_{1}", this.Name, this.isInteractive ? "Interactive" : "NonInteractive");
            }

            return base.ToString();
        }
    }
}
